package com.meida.module.arc.iam.task;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.cims.sync.constant.JsonResult;
import com.meida.common.base.constants.CommonConstants;
import com.meida.common.utils.DateUtil;
import com.meida.module.admin.client.constants.BaseConstants;
import com.meida.module.admin.client.entity.BaseAccount;
import com.meida.module.admin.client.entity.BaseUser;
import com.meida.module.admin.provider.service.BaseAccountService;
import com.meida.module.admin.provider.service.BaseUserService;
import com.meida.module.arc.iam.utils.JsonUtil;
import com.meida.module.system.client.entity.SysConfig;
import com.meida.module.system.client.entity.SysDept;
import com.meida.module.system.provider.service.BaseConfigService;
import com.meida.module.system.provider.service.SysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <b>功能名：ArcDesotryScheduledTask</b><br>
 * <b>说明：</b><br>
 * <b>著作权：</b> Copyright (C) 2021 HUIFANEDU  CORPORATION<br>
 * <b>修改履历：
 *
 * @author 2022-02-25 jiabing
 */

@Component
// 启用定时任务
@EnableScheduling
@Slf4j
public class ArcPulliamScheduledTask {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
    private static RestTemplate restTemplate = new RestTemplate();
    @Value("${cims.appSecret}")
    private String appSecret;
    @Value("${cims.appId}")
    private String appId;
    @Value("${cims.authUrl}")
    private String authUrl;
    @Autowired
    BaseConfigService configService;

    @Autowired
    SysDeptService deptService;

    @Autowired
    BaseUserService baseUserService;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Autowired
    BaseAccountService baseAccountService;


    public String getToken() {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        LinkedMultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("grant_type", "client_credentials");
        params.add("client_id", appId);
        params.add("client_secret", appSecret);
        HttpEntity<LinkedMultiValueMap<String, Object>> mapHttpEntity = new HttpEntity<>(params, httpHeaders);
        ResponseEntity<JsonResult> rResponseEntity = restTemplate.postForEntity(authUrl + "/oauth/token", mapHttpEntity, JsonResult.class);
        JsonResult rt = rResponseEntity.getBody();
        String token = "";
        if (rt.getCode() == 1000) {
            token = JsonUtil.pojo2map(rt.getData()).get("token").toString();
        }
        log.info("获取token：" + token);
        return token;
    }

    // 晚上23点执行一次任务。
    @Scheduled(cron = "0 0 23 * * ?")
    public void performingTasks() {
        log.info("执行更新IAM组织人员数据 定时任务时间：{}", DateUtil.date2Str(new Date(), "yyyy-MM-dd HH:mm:ss"));


        //    1更新单位
        pullOrg();
        //    2更新人员
        pullAccount();
    }

    private void pullAccount() {
        SysConfig config = configService.getByProperty("configKey", "PULL_USER");

        Map<String, Object> params = new HashMap<>();
        params.put("appId", appId);
        if (null != config && !"0".equals(config.getConfigVal())) {
            params.put("syncTime", config.getConfigVal());
        }

        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Bearer " + getToken());
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> mapHttpEntity = new HttpEntity<>(JsonUtil.obj2json(params), headers);
        log.info("拉取账号信息请求:" + JsonUtil.obj2json(params));
        ResponseEntity<JsonResult> response = restTemplate.postForEntity(authUrl + "/rest/v1/issue/pull/user", mapHttpEntity, JsonResult.class);
        JsonResult body = response.getBody();
        log.info("拉取账号信息结果:" + JsonUtil.obj2json(body));

        List<BaseUser> userList = new ArrayList<>();
        List<BaseAccount> accountList = new ArrayList<>();
        JSONObject obj = JSONUtil.parseObj(body.getData());
        //String body = "{\"code\":1000,\"msg\":\"成功\",\"data\":{\"taskId\":\"41b5bb683d594080a528d01a74741aea\",\"hasPaged\":false,\"currentPage\":1,\"totalPage\":1,\"total\":3,\"hasNext\":false,\"timestamp\":null,\"data\":[{\"syncType\":0,\"eventTimestamp\":1640157837722,\"createTime\":\"2021-12-22T07:23:57.729+0000\",\"taskId\":\"b320ae9c45674429b7078be2fa28626f\",\"appId\":\"659240c7ae18415e945cdab21e822cd3\",\"principalId\":\"cszh2\",\"password\":null,\"status\":\"0\",\"sort\":null,\"attributes\":{\"deptNums\":\",csbm2,\",\"address\":\"北京市海淀区\",\"gender\":\"男\",\"userName\":\"cszh1\"},\"deptNums\":[\"csbm2\"],\"appRoles\":[]}]}}";
        //JSONObject obj1 = JSONUtil.parseObj(body);
        //JSONObject obj = JSONUtil.parseObj(obj1.getStr("data"));
        JSONArray data = JSONUtil.parseArray(obj.getStr("data"));
        for (int i = 0; i < data.size(); i++) {
            JSONObject o = (JSONObject) data.get(i);
            BaseUser user = new BaseUser();
            user.setCompanyId(1517049905770037000L);

            user.setNickName(o.getStr("principalId"));
            user.setUserName(o.getStr("principalId"));
            user.setAccount(o.getStr("principalId"));
            user.setPassword(o.getStr("password"));
            user.setStatus(o.getInt("status"));

            BaseUser userByUsername = baseUserService.getUserByUsername(user.getAccount());
            if (ObjUtil.isNull(userByUsername)) {
                user.setUserId(IdWorker.getId());
            } else {
                user.setUserId(userByUsername.getUserId());
            }
            user.setStatus(CommonConstants.ENABLED);
            user.setUserType(CommonConstants.ENABLED_STR);
            String pwd = StrUtil.isEmpty(o.getStr("password")) ? "zbao@6888" : o.getStr("password");
            String encodePassword = passwordEncoder.encode(pwd);
            user.setPassword(encodePassword);
            JSONArray deptNums = o.getJSONArray("deptNums");
            SysDept one = deptService.getOne(new QueryWrapper<SysDept>().lambda().eq(SysDept::getDeptCode, deptNums.get(0)));
            user.setDeptId(one.getDeptId());
            userList.add(user);
            BaseAccount baseAccount = new BaseAccount(user.getUserId(), user.getUserName(), user.getPassword(), BaseConstants.USER_ACCOUNT_TYPE_USERNAME, BaseConstants.ACCOUNT_DOMAIN_ADMIN, null);
            baseAccount.setStatus(CommonConstants.ENABLED);
            accountList.add(baseAccount);

        }
        baseUserService.saveOrUpdateBatch(userList);
        baseAccountService.saveOrUpdateBatch(accountList);
        config.setConfigVal(System.currentTimeMillis() + "");
        config.updateById();
    }

    private void pullOrg() {
        SysConfig config = configService.getByProperty("configKey", "PULL_ORG");
        Map<String, Object> params = new HashMap<>();
        params.put("appId", appId);
        if (null != config && !"0".equals(config.getConfigVal())) {
            params.put("syncTime", config.getConfigVal());
        }
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Bearer " + getToken());
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> mapHttpEntity = new HttpEntity<>(JsonUtil.obj2json(params), headers);
        log.info("拉取组织信息请求:" + JsonUtil.obj2json(params));
        ResponseEntity<JsonResult> response = restTemplate.postForEntity(authUrl + "/rest/v1/issue/pull/org", mapHttpEntity, JsonResult.class);
        JsonResult body = response.getBody();
        log.info("拉取组织信息结果:" + JsonUtil.obj2json(body));

        JSONObject obj = JSONUtil.parseObj(body.getData());
        //String body = "{\"code\":1000,\"msg\":\"成功\",\"data\":{\"taskId\":\"41b5bb683d594080a528d01a74741aea\",\"hasPaged\":false,\"currentPage\":1,\"totalPage\":1,\"total\":3,\"hasNext\":false,\"timestamp\":null,\"data\":[{\"syncType\":0,\"eventTimestamp\":1640155309828,\"createTime\":\"2021-12-22T06:41:50.018+0000\",\"taskId\":\"41b5bb683d594080a528d01a74741aea\",\"appId\":\"659240c7ae18415e945cdab21e822cd3\",\"name\":\"测试部门 2\",\"status\":\"0\",\"depNum\":\"csbm2\",\"parentNum\":null,\"parentNums\":\"csbm2\",\"sort\":0,\"attrs\":{\"depType\":\"一级部门\",\"name\":\"测试部门 2\",\"parentNum\":null,\"depNum\":\"csbm2\",\"depStatus\":\"有效\"}}]}}";
        //JSONObject obj1 = JSONUtil.parseObj(body);
        //JSONObject obj = JSONUtil.parseObj(obj1.getStr("data"));
        JSONArray data = JSONUtil.parseArray(obj.getStr("data"));
        List<SysDept> deptList = new ArrayList<>();
        for (int i = 0; i < data.size(); i++) {
            JSONObject o = (JSONObject) data.get(i);
            SysDept dept = new SysDept();
            dept.setCompanyId(1517049905770037000L);
            dept.setDeptNo(o.getStr("depNum"));
            dept.setDeptCode(o.getStr("depNum"));
            dept.setDeptName(o.getStr("name"));
            dept.setDeptState(o.getInt("status"));
            dept.setSortOrder(o.getInt("sort"));
            dept.setParentId(0L);
            SysDept deptCode = deptService.getOne(new QueryWrapper<SysDept>().eq("deptCode", dept.getDeptCode()));
            if(ObjUtil.isNotNull(deptCode)){
                dept.setDeptId(deptCode.getDeptId());
            }
            if (StrUtil.isNotEmpty(o.getStr("parentNum"))) {
                //    查找上级ID
                SysDept parent = deptService.getOne(new QueryWrapper<SysDept>().lambda().eq(SysDept::getDeptCode, o.getStr("parentNum")));
                dept.setParentId(parent.getDeptId());
            }
            deptList.add(dept);
        }

        deptService.saveOrUpdateBatch(deptList);

        config.setConfigVal(System.currentTimeMillis() + "");
        config.updateById();
    }
}
